<?php defined('SYSPATH') or die('No direct script access.');

/**
 *Copyright www.stourweb.com
 *Author: nilsir
 *QQ: 2758691158
 *Time: 2017/7/18 14:07
 *Desc: WAP端支付宝支付
 */
class Controller_Mobile_Alipay extends Stourweb_Controller
{
    private $_id = 1;
    //支付宝即时交易目录
    private $_alipay_dir;
    //异步通知
    private $_notify_url;
    //同步通知
    private $_return_url;
    //操作中断返回地址
    private $_error_url;
	//不同版本下获取头部底部
    public $content;

    public function before()
    {
        parent::before();
        $this->_alipay_dir = ALIPAY . 'vendor' . DS . 'mobile' . DS . 'alipay' . DS;

        $domain = St_Functions::get_main_host();
        $m_main_url = $GLOBALS['cfg_m_main_url'];
//        $mobile_domain = $m_main_url == $domain ? $domain . '/phone' : $m_main_url;
        //增加手机域名为空时的判断
        if(empty($m_main_url) || $m_main_url == $domain)
        {
            $mobile_domain = $domain.'/phone';
        }
        else
        {
            $mobile_domain = $m_main_url;
        }
		
		$returnurl = St_Filter::remove_xss(Arr::get($_GET,'returnurl'));
		
        $this->_notify_url = $mobile_domain . '/alipay/mobile/notify_url/';
        $this->_return_url = $returnurl ? $GLOBALS['cfg_basehost'].$returnurl : $mobile_domain . '/alipay/mobile/return_url/';
        $this->_error_url = $mobile_domain . '/alipay/mobile/error_url/';
		
		if (empty($this->content))
        {
            $temp = rtrim(BASEPATH, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR .
                'data' . DIRECTORY_SEPARATOR .
                'cache' . DIRECTORY_SEPARATOR .
                'payment' . DIRECTORY_SEPARATOR .
                'common' . DIRECTORY_SEPARATOR;
            $file = $temp . 'mobile.php';

            if (file_exists($file) && (time() - filemtime($file)) < 600)
            {
                $this->content = file_get_contents($file);
            }
            else
            {
                if (!file_exists(dirname($file)))
                {
                    mkdir(dirname($file), 0777, true);
                }
                $this->content = $this->file_get_content(Common::get_main_host() . '/phone/pub/pay');
                file_put_contents($file, $this->content);
            }
        }
    }

    /**
     * @function 支付宝支付入口
     */
    public function action_index()
    {

		//支付宝微信客户端
        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false)
        {
            $view = View::factory( 'mobile' . DIRECTORY_SEPARATOR . 'alipay_wxclient');

            $conf = require dirname(DOCROOT) . '/data/mobile.php';
            $__url=explode('?',$_SERVER['HTTP_REFERER']);
            $back_url=$__url[0].'?'.$_SERVER['QUERY_STRING'];
            $url = Common::get_main_host() . '/phone/';
            //增加手机域名为空时的判断
            if (stripos($conf['domain']['mobile'], $url) === false&&!empty($conf['domain']['mobile']))
            {
                $url = $conf['domain']['mobile'];
            }
            $view = str_replace(
                array(
                    '<stourweb_pay_content/>',
                    '<stourweb_title/>',
                    '确认订单',
                    '产品支付',
                    'href="'.$url.'"'
                ),
                array(
                    $view->render(),
                    '支付宝微信端支付',
                    '订单支付',
                    '订单支付',
                    'href="'.$back_url.'"'
                ),
                $this->content
            );
            exit($view);
        }
        $ordersn = Common::remove_xss(Arr::get($_GET, 'ordersn'));
        $info = Model_Member_Order::info($ordersn);
        $info['typename'] = Model_Model::get_module_name($info['typeid']);
        self::_checked_ordersn($ordersn);
        $this->submit($info);
        exit;
    }

    public function action_uniapp_show()
    {
        //支付宝微信客户端
        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false)
        {
            $view = View::factory( 'mobile' . DIRECTORY_SEPARATOR . 'alipay_wxclient_uniapp');
            exit($view);
        }
        $ordersn = Common::remove_xss(Arr::get($_GET, 'ordersn'));
        $info = Model_Member_Order::info($ordersn);
        $info['typename'] = Model_Model::get_module_name($info['typeid']);
        self::_checked_ordersn($ordersn);
        $this->uniapp_submit($info);
        exit;
    }

    /**
     * uniapp-h5
     * @param $data
     */
    public function uniapp_submit($data) {
        require_once($this->_alipay_dir . "lib/alipay_submit2.class.php");
        $appid = Model_Sysconfig::get_configs(0, 'cfg_alipay_appid', true);
        $returnUrl = $this->_return_url;
        $notifyUrl = $this->_notify_url;
        $outTradeNo = $data['ordersn'];
        $payAmount = $data['total'];
        $orderName = $data['ordersn'];
        $projectName = St_Functions::replaceSpecialChar($data['productname']) ;
        $signType = 'RSA2';
        $rsaPrivateKey=Model_Sysconfig::get_configs(0, 'merchant_private_key', true);
        $aliPay = new AlipaySubmit($appid,$returnUrl,$notifyUrl,$rsaPrivateKey);
        $payConfigs = $aliPay->doPay($payAmount,$outTradeNo,$orderName,$returnUrl,$notifyUrl,$signType,$projectName);
        $queryStr = http_build_query($payConfigs);
        header("Location:https://openapi.alipay.com/gateway.do?{$queryStr}");
    }

    /**
     * phone端
     * @function 提交订单数据
     * @param $data
     */
    public function submit($data)
    {
        require_once($this->_alipay_dir . "lib/alipay_submit.class.php");
        header('Content-type:text/html; Charset=utf-8');
        /*** 请填写以下配置信息 ***/
        //https://open.alipay.com 账户中心->密钥管理->开放平台密钥，填写添加了电脑网站支付的应用的APPID
        $appid = Model_Sysconfig::get_configs(0, 'cfg_alipay_appid', true);
        //付款成功后的同步回调地址
        $returnUrl = $this->_return_url;
        //付款成功后的异步回调地址
        $notifyUrl = $this->_notify_url;
        //你自己的商品订单号
        $outTradeNo = $data['ordersn'];
        //付款金额，单位:元
        $payAmount = $data['total'];
        //订单标题
        $orderName = $data['ordersn'];
        //商品名
        $productname = $data['productname'];
        //签名算法类型，支持RSA2和RSA，推荐使用RSA2
        $signType = 'RSA2';
        //商户私钥，填写对应签名算法类型的私钥，如何生成密钥参考：https://docs.open.alipay.com/291/105971和https://docs.open.alipay.com/200/105310
        $rsaPrivateKey=Model_Sysconfig::get_configs(0, 'merchant_private_key', true);
        /*** 配置结束 ***/
        $aliPay = new AlipaySubmit();
        $aliPay->setAppid($appid);
        $aliPay->setReturnUrl($returnUrl);
        $aliPay->setNotifyUrl($notifyUrl);
        $aliPay->setRsaPrivateKey($rsaPrivateKey);
        $aliPay->setTotalFee($payAmount);
        $aliPay->setOutTradeNo($outTradeNo);
        $aliPay->setOrderName($orderName);
        $aliPay->setSignType($signType);
        $aliPay->setProjectName($productname);
        $sHtml = $aliPay->doPay();
        echo $sHtml;
    }

    /**
     * @function 检测订单状态
     * @param $ordersn
     * @return bool
     */
    private static function _checked_ordersn($ordersn)
    {
        $bool = false;
        $info['ordersn'] = $ordersn;
        if (! preg_match('~^\d+$~', $ordersn))
        {
            //订单号格式错误
            $info['sign'] = 25;
        }
        else if (Model_Member_Order::not_exists($ordersn))
        {
            //订单不存在
            $info['sign'] = 26;
        }
        else if (Model_Member_Order::payed($ordersn))
        {
            //订单已支付
            $info['sign'] = 24;
        }
        else
        {
            $bool = true;
        }
        //订单号错误提示
        if (! $bool)
        {
            St_Payment::pay_status($info);
            exit;
        }

        return $bool;
    }

    /**
     * @function 服务器异步通知页面路径
     * @return string
     * "gmt_create": "2021-12-07 17:05:48",
    "charset": "utf-8",
    "seller_email": "one@letuantuan.cn",
    "subject": "11421120716522778241",
    "sign": "D0nETtkdOjkWYPqRf5oeVvHmYcZqgja7Botu/3ovUTgO2C5FyGYqDSt30oMDz/L6ADWoWlcVVXxpnu/g5ppQXTjmPgmXkqSWD03UEw5ku+7ylE2f0NIMlt6vOx8u1+wrnsqx0uKoKc3+3xncKDBNnucQCzBSS3UDlO6DndDYxFxpJrot/cAKhQCowCNRxF1qrfjrUu7/VtYWpI+S+IMav6w5j+9SyKgYPMsVekFkJA5hqwsvXRSDmUdaJZ7Z77BU8BhPD9j1g/IXYyRfvOM4s1HM+YKw6X30v5QXadHMogRR7GlTrQEWmJRrXC4p5jwd+NyMkqcS7Mowbf7icdPrEA==",
    "buyer_id": "2088112729103664",
    "invoice_amount": "0.01",
    "notify_id": "2021120700222170549003661426890032",
    "fund_bill_list": "[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
    "notify_type": "trade_status_sync",
    "trade_status": "TRADE_SUCCESS",
    "receipt_amount": "0.01",
    "buyer_pay_amount": "0.01",
    "app_id": "2021001159660839",
    "sign_type": "RSA2",
    "seller_id": "2088631043045536",
    "gmt_payment": "2021-12-07 17:05:49",
    "notify_time": "2021-12-07 17:05:50",
    "version": "1.0",
    "out_trade_no": "11421120716522778241",
    "total_amount": "0.01",
    "trade_no": "2021120722001403661433613116",
    "auth_app_id": "2021001159660839",
    "buyer_logon_id": "183***@163.com",
    "point_amount": "0.00"
     */
    public function action_notify_url()
    {
        header('Content-type:text/html; Charset=utf-8');
        include($this->_alipay_dir . 'lib/alipay_notify.class.php');
        //支付宝公钥，账户中心->密钥管理->开放平台密钥，找到添加了支付功能的应用，根据你的加密类型，查看支付宝公钥
        $alipayPublicKey=Model_Sysconfig::get_configs(0, 'alipay_public_key', true);
        $aliPay = new AlipayNotify($alipayPublicKey);
        //验证签名
        $result = $aliPay->rsaCheck($_POST);
        if($result===true){
            //处理你的逻辑，例如获取订单号$_POST['out_trade_no']，订单金额$_POST['total_amount']等
            //程序执行完后必须打印输出“success”（不包含引号）。如果商户反馈给支付宝的字符不是success这7个字符，支付宝服务器会不断重发通知，直到超过24小时22分钟。一般情况下，25小时以内完成8次通知（通知的间隔频率一般是：4m,10m,10m,1h,2h,6h,15h）；
            if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                if (St_Payment::total_fee_confirm($_POST['out_trade_no'], $_POST['total_amount'])) {
                    $payset = Model_Payset::get_payset_info_by_id($this->_id);
                    //写入支付宝流水号
                    $online_transaction_no = array('source'=>'alipay','transaction_no'=>$_POST['trade_no']);
                    DB::update('member_order')->set(array('online_transaction_no'=>json_encode($online_transaction_no)))
                        ->where('ordersn','=',$_POST['out_trade_no'])
                        ->execute();
                    St_Payment::pay_success($_POST['out_trade_no'], $payset['name'] . '(手机端)');

                }
            } else {
                new Pay_Exception("状态:{$_POST['trade_status']}");
            }
            echo 'success';
            exit();
        }
        new Pay_Exception("信息:合法性验证失败");
        echo 'error';
        exit();
    }

    /**
     * @function 页面跳转同步通知页面路径
     */
    public function action_return_url()
    {
        St_Functions::writeLog(1,__LINE__,'test.log');
        header('Content-type:text/html; Charset=utf-8');
        include($this->_alipay_dir . 'lib/alipay_notify.class.php');
        //支付宝公钥，账户中心->密钥管理->开放平台密钥，找到添加了支付功能的应用，根据你的加密类型，查看支付宝公钥
        $alipayPublicKey=Model_Sysconfig::get_configs(0, 'alipay_public_key', true);;
        $aliPay = new AlipayNotify($alipayPublicKey);
        //验证签名
        $result = $aliPay->rsaCheck($_GET);
        if ($result) {
            $info['sign'] = '11';
        } else {
            $info['sign'] = '22';
            new Pay_Exception("信息:支付宝手机支付(同)合法性验证失败");
        }
        $info['ordersn'] = $_GET['out_trade_no'];
        self::_write_log($this->request->action());
        St_Payment::pay_status($info);
    }

    /**
     * @function 支付终端操作
     */
    public function action_error_url()
    {
        $info['sign'] = '01';
        $info['ordersn'] = $_GET['out_trade_no'];
        St_Payment::pay_status($info);
    }

    /**
     * @function 将回调参数写入日志文件
     * @param $method
     */
    private static function _write_log($method)
    {
        $pay_class = __CLASS__;
        $pay_log_dir = APPPATH . 'logs/pay/';
        if (! file_exists($pay_log_dir))
        {
            mkdir($pay_log_dir, 0777, true);
        }
        //日志文件
        $file = $pay_log_dir . str_replace('pay_', '', strtolower($pay_class)) . '_' . date('ymd') . '.txt';
        $data = "\r\n[{$method}:" . date('YmdHis');
        foreach ($_REQUEST as $k => $v)
        {
            $data .= " {$k}={$v}";
        }
        $data .= ']';
        file_put_contents($file, $data, FILE_APPEND);
    }

    /**
     * @function 获取远程数据
     * @param $url
     * @return mixed
     */
    public function file_get_content($url) {
        $ch=  curl_init($url);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $content = curl_exec($ch);
        curl_close($ch);
        return $content;
    }
}